﻿/************************************************************************
 * AIDE - Automata Identification Engine
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     AIDE\Oracles\DFAs\Oracle_MAT_DFA_Ideal.cs
 * Description  :     An ideal oracle for learning DFAs in MAT setting
 * Change log   :     -April 2013: Initial draft
 * To Do        :     -It is not fully implemented!!
 ************************************************************************/

using System;
using System.Collections.Generic;
using SMLib.Automata.Base;
using SMLib.Automata.DFA;

namespace AIDE.Oracles.DFAs
{
    /// <summary>
    /// The Teacher/Oracle in the Angluin algorithm when you have a DFA as the real implementation
    /// </summary>
    public class Oracle_MAT_DFA_Realistic : IOracle_MAT_DFA
    {
        public int numberOgMQ = 0, numberOfEQ = 0;

        IBlackBox_RegLanguage SUL;
        Alphabet MyAlphabet;

        /// <summary>
        /// Constructor of the ideal oracle
        /// </summary>
        /// <param name="sut">the underlaying DFA</param>
        public Oracle_MAT_DFA_Realistic(IBlackBox_RegLanguage SUL)
        {
            this.SUL = SUL;
            this.MyAlphabet = SUL.InputAlphabet;
        }

        /// <summary>
        /// Check whether a word is accepting or not
        /// </summary>
        /// <param name="a">the word to be checked</param>
        /// <returns>true, if accepting. false if not</returns>
        public bool MembershipQuery(Word a)
        {
            return SUL.isAccepting(a);
        }


        /// <summary>
        /// See if to DFA are equal myOracle NEG. If they are not equal, find a counterexample to show the difference
        /// <remarks>[To Do: not implemented yet]</remarks>
        /// </summary>
        /// <param name="conjucture">the conjecture to be compared with</param>
        /// <returns>
        /// if null, the models are the same.
        /// if not null, it is a counterexample which shows the models are not the same
        /// </returns>
        public Word EquivalenceQuery(DFA conjucture)
        {
            numberOfEQ++;
/*			
			
			if(numberOfEQ==1)
			{
				return	Word.TryParse("b.a");
			}
			else if(numberOfEQ==2)
			{
				return 	Word.TryParse("a.b.a.a");				
			}
			else if(numberOfEQ==3)
			{
				//return Word.TryParse("b.b");
			}
			
            */
            //AIDE.Automata.Utils.AutomataUtils.DrawAutomata(conjucture);
            //OTCG_WMethod tcg = new OTCG_WMethod(conjucture);
            //tcg.Process();
            //tcg.GenerateTestSuite();
            //foreach (Word w in tcg.TestSequences())
            //{
            //    bool b1 = SUL.isAccepting(w);
            //    bool b2 = tmpOracle.MembershipQuery(w);
            //    if (b1 != b2)
            //        return w;
            //}
            //* random testing!
			Oracle_MAT_DFA_Ideal tmpOracle = new Oracle_MAT_DFA_Ideal(conjucture);
            Random rnd = new Random();
            for (int i = 0; i < 1000; i++)
            {
                int l = rnd.Next(conjucture.Size * 2);
                Word w = new Word();
                for (int j = 0; j < l; j++)
                {
                    w.AddSymbol(MyAlphabet[rnd.Next(MyAlphabet.Size)]);
                }
                bool b1 = SUL.isAccepting(w);
                bool b2 = tmpOracle.MembershipQuery(w);
                if (b1 != b2)
				{
					//Console.WriteLine("Counterexample "+w);
					//Console.WriteLine("\tOn SUL:"+b1);
					//Console.WriteLine("\tOn Conjecture:"+b2);
                    return w;
				}
				
            }
            return null;
        }

        #region IOracle_MAT_DFA Members

        /// <summary>
        /// The input alphabet (Sigma)
        /// </summary>
        public Alphabet inputAlphabet
        {
            get { return MyAlphabet; }
        }

        #endregion
    }
}
